package nio.channel.filechannel;

import org.junit.Test;

import java.io.*;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

/**
 * @author charwayH
 */
public class ChannelTest {

    /**
     * 写数据
     */
    @Test
    public void write() throws IOException {
        // 1.字节输出流通向目标文件
        FileOutputStream fos = new FileOutputStream("/Users/charwayh/Desktop/java-myself/hello-net-io/src/main/java/nio/channel/filechannel/data01.txt");
        // 2. 得到字节输出流对应的通道Channel
        FileChannel channel = fos.getChannel();
        // 3. 分配缓冲区
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        buffer.put("hello CharwayH".getBytes());
        // 4.把缓冲区切换为写出模式
        buffer.flip();
        channel.write(buffer);
        channel.close();
        System.out.println("写出数据到文件...");
    }

    /**
     * 读数据
     */
    @Test
    public void read() throws IOException {
        // 1. 定义一个字节输入流和源文件接通
        FileInputStream fis = new FileInputStream("/Users/charwayh/Desktop/java-myself/hello-net-io/src/main/java/nio/channel/filechannel/data01.txt");
        // 2. 需要得到文件字节输入流的文件管道
        FileChannel channel = fis.getChannel();
        // 3. 定义一个缓冲区
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        // 4. 读取数据到缓冲区
        channel.read(buffer);
        // position改为0
        buffer.flip();
        // 5.读取缓冲区中的数据并输出
        String rs = new String(buffer.array(),0,buffer.remaining());
        System.out.println(rs);
    }


    /**
     * 复制文件
     */
    @Test
    public void copy() throws IOException {
        // 源文件
        File srcFile = new File("/Users/charwayh/Desktop/java-myself/hello-net-io/src/main/java/nio/channel/filechannel/data01.txt");
        // 得到一个字节输出流和字节输入流
        FileInputStream fis = new FileInputStream(srcFile);
        FileOutputStream fos = new FileOutputStream("/Users/charwayh/Desktop/java-myself/hello-net-io/src/main/java/nio/channel/filechannel/newdata01.txt");
        // 得到文件通道
        FileChannel fisChannel = fis.getChannel();
        FileChannel fosChannel = fos.getChannel();
        // 分配缓冲区
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        while (true){
            // 必须先清空缓冲区在写入数据到缓冲区
            buffer.clear();
            // 开始读取一次数据
            int flag = fisChannel.read(buffer);
            if(flag == -1){
                break;
            }
            // 已经读到的数据，把缓冲区的模式切换到可读模式
            buffer.flip();
            // 把数据写到目标文件中
            fosChannel.write(buffer);
        }
        fisChannel.close();
        fosChannel.close();
        System.out.println("复制完成...");
    }

    /**
     * 分散读取和聚集写入
     * @throws IOException
     */
    @Test
    public void test04() throws IOException {
        // 1.字节输入流管道
        FileInputStream fis = new FileInputStream("/Users/charwayh/Desktop/java-myself/hello-net-io/src/main/java/nio/channel/filechannel/data01.txt");
        FileChannel fisChannel = fis.getChannel();
        // 2.字节输出流管道
        FileOutputStream fos = new FileOutputStream("/Users/charwayh/Desktop/java-myself/hello-net-io/src/main/java/nio/channel/filechannel/data02.txt");
        FileChannel fosChannel = fos.getChannel();
        // 3.定义多个缓冲区做数据分散
        ByteBuffer buffer1 = ByteBuffer.allocate(4);
        ByteBuffer buffer2 = ByteBuffer.allocate(1024);
        ByteBuffer[] byteBuffers = {buffer1,buffer2};
        // 4. 从管道中读取数据到各个缓冲区
        fisChannel.read( byteBuffers);
        // 5. 从各个缓冲区中查询是否已经读取到数据
        for (ByteBuffer buffer : byteBuffers) {
            // 切换到读模式
            buffer.flip();
            System.out.println(new String(buffer.array(),0,buffer.remaining()));
        }
        // 6.聚集写消息到通道
        fosChannel.write(byteBuffers);
        fisChannel.close();
        fosChannel.close();
        System.out.println("文件复制完毕...");
    }

    /**
     * transferFrom 和transferTo
     */
    @Test
    public void test05() throws IOException {
        // 1.字节输入流管道
        FileInputStream fis = new FileInputStream("/Users/charwayh/Desktop/java-myself/hello-net-io/src/main/java/nio/channel/filechannel/data01.txt");
        FileChannel fisChannel = fis.getChannel();
        // 2.字节输出流管道
        FileOutputStream fos = new FileOutputStream("/Users/charwayh/Desktop/java-myself/hello-net-io/src/main/java/nio/channel/filechannel/data04.txt");
        FileChannel fosChannel = fos.getChannel();

        // 3.复制数据
        fosChannel.transferFrom(fisChannel, fisChannel.position(), fisChannel.size());
        // transferTo与transferFrom相反
        // fisChannel.transferTo(fisChannel.position(),fisChannel.size() , fosChannel);
        fisChannel.close();
        fosChannel.close();

    }

}
